package com.upcode.weighing.gateway.filter;

import com.upcode.weighing.common.enums.HttpStatus;
import com.upcode.weighing.gateway.util.PassWordUtils;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.netflix.zuul.filters.post.SendErrorFilter;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.cloud.netflix.zuul.util.ZuulRuntimeException;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;

import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author zyw
 * @date 2018/2/9
 */
@Component
public class CaptchaZuulFilter extends ZuulFilter {
    protected static final String SEND_ERROR_FILTER_RAN = "sendErrorFilter.ran";
    private static final Logger logger= LoggerFactory.getLogger(CaptchaZuulFilter.class);
    @Value("${error.path:/error}")
    private String errorPath;

    @Value("${zuul-filter.check-image-verification-code}")
    private boolean checkImgVerificationCode;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }


    @Override
    public int filterOrder() {
        return -2;
    }

    @Override
    public boolean shouldFilter() {
        RequestContext ctx = RequestContext.getCurrentContext();
        return ctx.getRequest().getRequestURI().contains("/oauth/token");
    }


    @Override
    public Object run() {
        SendErrorFilter a;
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest req = ctx.getRequest();
        String clientId = req.getParameter("client_id");
        try {
            if (StringUtils.equals(clientId, "webapp")) {//管理系统图片验证码
                //图片验证码的过滤处理,调试的时候如果不需要校验验证码,可以将如下代码注释
                logger.debug("checkImgVerificationCode:"+checkImgVerificationCode);
                if (checkImgVerificationCode) {//web系统图片验证码
                    String captcha = req.getParameter("captcha");
                    String captchaKey = req.getParameter("captchaKey");

                    if (StringUtils.isEmpty(captcha)) {
                        logger.warn("图片验证码为空");
                        throw new ZuulRuntimeException(new ZuulException(HttpStatus.NSOP_CAPTCHA_NULL.msg(), HttpStatus.NSOP_CAPTCHA_NULL.value(), HttpStatus.NSOP_CAPTCHA_NULL.msg()));
                    }
                    String redisCaptcha = stringRedisTemplate.boundValueOps(captchaKey).get();

                    if (!StringUtils.equalsIgnoreCase(captcha, redisCaptcha)) {
                        logger.warn("图片验证码输入错误");
                        throw new ZuulRuntimeException(new ZuulException(HttpStatus.NSOP_CAPTCHA_ERROR.msg(), HttpStatus.NSOP_CAPTCHA_ERROR.value(), HttpStatus.NSOP_CAPTCHA_ERROR.msg()));
                    }
                }

            } else if (StringUtils.equals(clientId, "verification")) {//app短信验证码
                String mobile = req.getParameter("username");//手机号
                String code = req.getParameter("password");//手机验证码
//                try {
//                	code = PassWordUtils.decrypt(code, pwdPrivateKey);
//         		} catch (Exception e) {
//         			e.printStackTrace();
//         		}
                if (StringUtils.isEmpty(code)) {
                    logger.warn("短信验证码为空");
                    throw new ZuulRuntimeException(new ZuulException(HttpStatus.NSOP_CAPTCHA_NULL.msg(), HttpStatus.NSOP_CAPTCHA_NULL.value(), HttpStatus.NSOP_CAPTCHA_NULL.msg()));
                }
                String redisCaptcha = stringRedisTemplate.boundValueOps(mobile).get();
                if (null == redisCaptcha) {
                    throw new ZuulRuntimeException(new ZuulException(HttpStatus.NSOP_CAPTCHA_INVALID.msg(), HttpStatus.NSOP_CAPTCHA_INVALID.value(), HttpStatus.NSOP_CAPTCHA_INVALID.msg()));
                }
                if (!StringUtils.equals(code, redisCaptcha)) {
                    throw new ZuulRuntimeException(new ZuulException(HttpStatus.NSOP_CAPTCHA_ERROR.msg(), HttpStatus.NSOP_CAPTCHA_ERROR.value(), HttpStatus.NSOP_CAPTCHA_ERROR.msg()));
                }
            }
        } catch (Exception e) {
            try {
                ZuulException exception = findZuulException(e);
                HttpServletRequest request = ctx.getRequest();

                request.setAttribute("javax.servlet.error.status_code", exception.nStatusCode);
                request.setAttribute("javax.servlet.error.exception", exception);

                if (org.springframework.util.StringUtils.hasText(exception.errorCause)) {
                    request.setAttribute("javax.servlet.error.message", exception.errorCause);
                }

                RequestDispatcher dispatcher = request.getRequestDispatcher(
                        this.errorPath);
                if (dispatcher != null) {
                    ctx.set(SEND_ERROR_FILTER_RAN, true);
                    if (!ctx.getResponse().isCommitted()) {
                        ctx.setResponseStatusCode(exception.nStatusCode);

                        //下面的代码是调试解决跨域结束使用使用，不能提交线上
//                        HttpServletResponse response = ctx.getResponse();
//                        response.setContentType("application/json");
//                        response.setCharacterEncoding("UTF-8");
//                        response.setContentType("text/html;charset=UTF-8");
//
//                        response.addHeader("Access-Control-Allow-Methods", "POST,GET,OPTIONS,HEAD,DELETE,PATCH");
//                        response.addHeader("Access-Control-Allow-Origin", "*");
//                        response.addHeader("Access-Control-Allow-Headers", "*");
                        //////////////解决跨域结束//////////////////

                        dispatcher.forward(request, ctx.getResponse());
                    }
                }
            } catch (Exception ex) {
                ReflectionUtils.rethrowRuntimeException(ex);
            }
        }


        return null;
    }

    ZuulException findZuulException(Throwable throwable) {
        if (throwable.getCause() instanceof ZuulRuntimeException) {
            // this was a failure initiated by one of the local filters
            return (ZuulException) throwable.getCause().getCause();
        }

        if (throwable.getCause() instanceof ZuulException) {
            // wrapped zuul exception
            return (ZuulException) throwable.getCause();
        }

        if (throwable instanceof ZuulException) {
            // exception thrown by zuul lifecycle
            return (ZuulException) throwable;
        }

        // fallback, should never get here
        return new ZuulException(throwable, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, null);
    }
    /**
     * 图片验证码的过滤处理
     *
     * @param ctx
     * @param req
     */
    private void filterImgVerificationCode(RequestContext ctx, HttpServletRequest req) {
        String captcha = req.getParameter("captcha");
        String captchaKey = req.getParameter("captchaKey");

        if (StringUtils.isEmpty(captcha)) {
            addHeaderPerproties(ctx);
            throw new ZuulRuntimeException(new ZuulException(HttpStatus.NSOP_CAPTCHA_NULL.msg(), HttpStatus.NSOP_CAPTCHA_NULL.value(), HttpStatus.NSOP_CAPTCHA_NULL.msg()));
        }
        String redisCaptcha = stringRedisTemplate.boundValueOps(captchaKey).get();
        if (!StringUtils.equalsIgnoreCase(captcha, redisCaptcha)) {
            addHeaderPerproties(ctx);
            throw new ZuulRuntimeException(new ZuulException(HttpStatus.NSOP_CAPTCHA_ERROR.msg(), HttpStatus.NSOP_CAPTCHA_ERROR.value(), HttpStatus.NSOP_CAPTCHA_ERROR.msg()));
        }
    }

    /**
     * 向header中添加属性,解决跨域问题
     *
     * @param ctx
     */
    private void addHeaderPerproties(RequestContext ctx) {
        HttpServletResponse response = ctx.getResponse();
        response.setContentType("application/json");
        response.setCharacterEncoding("UTF-8");
        response.addHeader("Access-Control-Allow-Methods", "POST,GET,OPTIONS,HEAD,DELETE,PATCH");
        response.addHeader("Access-Control-Allow-Origin", "*");
        response.addHeader("Access-Control-Allow-Headers", "*");
    }
}